
/***********************************************************************************************************************
* Copyright (C) . All rights reserved.
***********************************************************************************************************************/

/***********************************************************************************************************************
* File Name    : main.c
* Version      :  
* Device(s)    : BAT32G157
* Tool-Chain   : MDK(armcc)
* Description  : This file is a template.
* Creation Date: 2019/12/25
***********************************************************************************************************************/

#define MSG(arg) { printf arg ; }

/***********************************************************************************************************************
Includes
***********************************************************************************************************************/
#include "math.h"
#include "stdio.h"
#include "BAT32G157.h"
#include "userdefine.h"
#include "qspi.h"
#include "sci.h"

#define DATA_PRINT
#define FLASH_BASE  0x60000000
#define FLASH_ADDR  0x60002000

uint8_t rdata[256];
uint8_t wdata[256];
uint8_t err;

/***********************************************************************************************************************
Global variables and functions
***********************************************************************************************************************/
volatile uint32_t g_ticks;

void delayMS(uint32_t n)
{
		g_ticks = n;
		while(g_ticks);
}

int main (void)
{
	MD_STATUS status;
	uint32_t msCnt; 	// count value of 1ms
	uint32_t i;
	uint32_t div;
	int8_t n;
	
  uint32_t *ptr;	
	
//-----------------------------------------------------------------------
// Systick setting 
//-----------------------------------------------------------------------   
	g_ticks = 1000; 	// 1000ms
	SystemCoreClockUpdate();
	msCnt = SystemCoreClock / 1000;
	SysTick_Config(msCnt);

//-----------------------------------------------------------------------
// Init UART0 for retarget printf/scanf etc. 
//----------------------------------------------------------------------- 
#ifndef RTL_SIMULATION
	SystemCoreClockUpdate();
	status = UART0_Init(SystemCoreClock, 19200);
	if(status == MD_ERROR)
	{
		while(1); // The baud rate cannot get at the current system clock frequency.
	}
	
	printf("Hello, UART\n");
	printf("SPI Flash - Erase, Write and Fast Read Quad(6Bh/EBh)\n");
#endif
	
	//=========================================================================================
  // QSPI Setting
  //=========================================================================================
  SFMSSC = 0x00000001;  // the leading/trailing edge of SSB is 0.5 SCK, SSB high-level width 2 SCK
//  SFMSKC = 0x00000000;  // the period of SCK is 2 PCLK
	SFMSKC = 0x00000002;  // the period of SCK is 4 PCLK
  SFMSMD = 0x00000004;  // Fast Read Quad Output
  SFMPMD = 0x00000004;  // write protect disable

  //=========================================================================================
  // Initial write data
  //=========================================================================================
  for(i=0; i<256; i++) {
	wdata[i] = i;
  }

	//=========================================================================================
  // SPI Flash SoftReset
  //=========================================================================================	
	SoftReset();
	delayMS(1);
	MSG(("INFO: StatusRegister1 = 0x%02x\n", ReadStatus(STATUS_REG1)));
	MSG(("INFO: StatusRegister2 = 0x%02x\n", ReadStatus(STATUS_REG2)));
	
  //=========================================================================================
  // SPI Flash Write Protect Disable
  //=========================================================================================		
	if(ReadStatus(STATUS_REG1) != 0x00)
		WriteStatus(STATUS_REG1, 0x00);
	
  //=========================================================================================
  // Chip Erase
  //=========================================================================================
//  MSG(("INFO: Chip Erase...\n"));
//  EraseChip();
	
  //=========================================================================================
  // Block Erase (32KB Block Erase for W25Q128)
  //=========================================================================================
  MSG(("INFO: Block Erase...\n"));
  EraseBlock(FLASH_ADDR - FLASH_BASE);
	
  //=========================================================================================
  // Program
  //=========================================================================================
#if 1 
	MSG(("INFO: Page Program...\n"));
  for(i=0; i<4; i++) {
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0000 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 0]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0011 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 1]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0022 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 2]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0033 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 3]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0044 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 4]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0055 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 5]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0066 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 6]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0077 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 7]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0088 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 8]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0099 + 1 * i, 1, (uint8_t *)&wdata[1 * i + 9]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x00AA + 1 * i, 1, (uint8_t *)&wdata[1 * i + 10]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x00BB + 1 * i, 1, (uint8_t *)&wdata[1 * i + 11]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x00CC + 1 * i, 1, (uint8_t *)&wdata[1 * i + 12]);
  }
  for(i=0; i<4; i++) {
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0100 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 0]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0111 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 1]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0122 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 2]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0133 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 3]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0144 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 4]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0155 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 5]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0166 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 6]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0177 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 7]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0188 + 2 * i, 2, (uint8_t *)&wdata[2 * i + 8]);
  }
  for(i=0; i<4; i++) {
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0200 + 3 * i, 3, (uint8_t *)&wdata[3 * i + 0]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0211 + 3 * i, 3, (uint8_t *)&wdata[3 * i + 1]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0222 + 3 * i, 3, (uint8_t *)&wdata[3 * i + 2]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0233 + 3 * i, 3, (uint8_t *)&wdata[3 * i + 3]);
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0244 + 3 * i, 3, (uint8_t *)&wdata[3 * i + 4]);
  }
  for(i=0; i<4; i++) {
  	ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0300 + 4 * i, 4, (uint8_t *)&wdata[4 * i + 0]);
  }
  ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0400, 128, (uint8_t *)&wdata[0]);
  ProgramPage((FLASH_ADDR - FLASH_BASE) + 0x0480, 128, (uint8_t *)&wdata[128]);
#endif
  //=========================================================================================
  // QSPI Return to Read Mode
  //=========================================================================================
  if((ReadStatus(STATUS_REG2) & QE_Msk) == 0x00)
    WriteStatus(STATUS_REG2, QE_Msk);
  SFMCMD = 0x00U;  // ROM access mode
  SFMSSC = 0x00000000;  // the leading/trailing edge of SSB is 0.5 SCK, SSB high-level width 1 SCK
  SFMSMD = 0x00000004;  // Fast Read Quad Output

  MSG(("INFO: Read and Check data...\n"));
  MSG(("         00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15\n"));
#if 1
  //-----------------------------------------------------------------------------------------
  // Read Data section 1
  //-----------------------------------------------------------------------------------------
  ptr = (uint32_t *)rdata;
  for(i=0; i<52; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0000) + i));
  }

  // Check data section 1
  for(i=0; i<208; i++)
  {
      if((i / 16 <= i % 16) && (i % 16 < (i / 16 + 4)))
      {
          if(rdata[i] != wdata[i % 16]) err++;
      }
      else
      {
          if(rdata[i] != 0xFF) err++;
      }
  }

#ifdef DATA_PRINT
  // print data section 1
  for(i=0; i<208; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0000) + i));
      MSG((" %02X", rdata[i]));		
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif

  //-----------------------------------------------------------------------------------------
  // Read Data section 2
  //-----------------------------------------------------------------------------------------
  SFMSMD = 0x00000014;  // SPI Bus Cycle Extension(Extend SSB by 33 SCK), Fast Read Quad Output
  ptr = (uint32_t *)rdata;
  for(i=0; i<36; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0100) + i));
  }

  // Check data section 2
  for(i=0; i<144; i++)
  {
      if((i / 16 <= i % 16) && (i % 16 < (i / 16 + 8)))
      {
          if(rdata[i] != wdata[i % 16]) err++;
      }
      else
      {
          if(rdata[i] != 0xFF) err++;
      }
  }

#ifdef DATA_PRINT
  // print data section 2
  for(i=0; i<144; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0100) + i));
      MSG((" %02X", rdata[i]));
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif

  //-----------------------------------------------------------------------------------------
  // Read Data section 3
  //-----------------------------------------------------------------------------------------
  SFMSMD = 0x00000044;  // Prefetch enable, Fast Read Quad Output
  ptr = (uint32_t *)rdata;
  for(i=0; i<20; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0200) + i));
  }

  // Check data section 3
  for(i=0; i<80; i++)
  {
      if((i / 16 <= i % 16) && (i % 16 < (i / 16 + 12)))
      {
          if(rdata[i] != wdata[i % 16]) err++;
      }
      else
      {
          if(rdata[i] != 0xFF) err++;
      }
  }

#ifdef DATA_PRINT
  // print data section 3
  for(i=0; i<80; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0200) + i));
      MSG((" %02X", rdata[i]));
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif


  //-----------------------------------------------------------------------------------------
  // Read Data section 4
  //-----------------------------------------------------------------------------------------
  SFMSMD = 0x00000005;  // Fast Read Quad I/O
  SFMSDC = 0x0000AF80;  // XIP mode enable (Winbond)
  ptr = (uint32_t *)rdata;
  for(i=0; i<64; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0300) + i));
  }

  // Check data section 4
  for(i=0; i<16; i++)
  {
      if((i / 16 <= i % 16) && (i % 16 < (i / 16 + 16)))
      {
          if(rdata[i] != wdata[i % 16]) err++;
      }
      else
      {
          if(rdata[i] != 0xFF) err++;
      }
  }

#ifdef DATA_PRINT
  // print data section 4
  for(i=0; i<64; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0300) + i));
      MSG((" %02X", rdata[i]));
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif
#endif // comment out 4
  //-----------------------------------------------------------------------------------------
  // Read Data section 5-1
  //-----------------------------------------------------------------------------------------
  SFMSMD = 0x00000015;  // SPI Bus Cycle Extension(Extend SSB by 33 SCK), Fast Read Quad I/O
  SFMSDC = 0x0000FF00;  // XIP mode disable
  ptr = (uint32_t *)rdata;
  for(i=0; i<32; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0400) + i));
  }

  // Check data section 5-1
  for(i=0; i<128; i++)
  {
      if(rdata[i] != wdata[i]) err++;
  }

#ifdef DATA_PRINT
  // print data section 5-1
  for(i=0; i<128; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0400) + i));
      MSG((" %02X", rdata[i]));
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif

  //-----------------------------------------------------------------------------------------
  // Read Data section 5-2
  //-----------------------------------------------------------------------------------------
  SFMSMD = 0x00000045;  // Prefetch enable, Fast Read Quad I/O
  SFMSDC = 0x0000FF00;  // XIP mode disable
  for(i=32; i<64; i++)
  {
      *ptr++ = (*((uint32_t *)(FLASH_ADDR + 0x0400) + i));
  }

  // Check data section 5-2
  for(i=128; i<256; i++)
  {
      if(rdata[i] != wdata[i]) err++;
  }

#ifdef DATA_PRINT
  // print data section 5-2
  for(i=128; i<256; i++)
  {
	  if(i % 16 == 0) MSG(("0x%05X:", (FLASH_ADDR - FLASH_BASE + 0x0400) + i));
      MSG((" %02X", rdata[i]));
	  if(i % 16 == 15) MSG(("\n"));
  }
	MSG(("err = %d\n", err));
#endif
	
//=========================================================================================
// OK: LED ON
// NG: LED OFF
//=========================================================================================
	PORT->PMCD &= ~(3<<8);  // PD08, PD09 digital function
	PORT->PMD  &= ~(3<<8);  // PD08, PD09 output mode
	PORT->PD   |=  (3<<8);  // PD08/LED, PD09/LED OFF
 	if(err)
 	{
		for(i=0; i<8; i++)
		{
			PORT->PD ^= (1<<8);
	#ifndef RTL_SIMULATION
			delayMS(250);
	#endif
		}
		PORT->PSETD = (1<<8); 	// PD08/LED OFF
 	}
 	else
 	{
		for(i=0; i<8; i++)
		{
			PORT->PD ^= (1<<8);
	#ifndef RTL_SIMULATION
			delayMS(250);
	#endif
		}
		PORT->PCLRD = (1<<8); 	// PD08/LED ON
 	}
	
	while(1);

}

/***********************************************************************************************************************
* Function Name: SysTick Handler
* Description  : Decreament the g_ticks value
* Arguments    : None
* Return Value : None
***********************************************************************************************************************/
void SysTick_Handler(void)
{
	g_ticks--;
}
